package cn.com.cis.web.actions;

import cn.com.cis.domain.*;
import cn.com.cis.enums.MultipleThreadJobParams;
import cn.com.cis.enums.TemplateParamType;
import cn.com.cis.service.ConnectionService;
import cn.com.cis.service.GenerateXmlService;
import cn.com.cis.service.XmlJobService;
import cn.com.cis.utils.jobExecute.JobExecuteHelper;
import cn.com.cis.utils.security.Encodes;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Type;
import java.util.*;

@Controller
@RequestMapping(value = "/template_para")
public class TemplateController {
	
	@Autowired
	private XmlJobService xmlJobService;
	
	@Autowired
	private ConnectionService connectionService;
	
	@Autowired
	private GenerateXmlService generateXmlService;
	
	private void setNavigateBar(ModelAndView mv){
    	mv.addObject("icon", "icon-list");
        mv.addObject("title", "EtlXml作业");
    }

	// 用于jqGrid加载数据
	@RequestMapping(value = "/data", method = RequestMethod.GET)
	@ResponseBody
	public DataResponse<TemplateParamDef> listParams(int tempId) {
		DataResponse<TemplateParamDef> response = new DataResponse<TemplateParamDef>();
		
		List<TemplateParamDef> paramDefs = xmlJobService.selectNonThreadParamDefsByTemplateId(tempId);
		for(TemplateParamDef param : paramDefs){
			TemplateParamType paramType = TemplateParamType.fromString(param.getParamType());
			param.setParamType(paramType.getHumanReadableName());
		}
		
		response.getRows().addAll(paramDefs);
		
		return response;
	}
	
	@RequestMapping(value = "/doNothing", method = RequestMethod.POST)
	@ResponseBody
	public String responseNone(HttpServletRequest request) {
		return "";
	}
	
	@RequestMapping(value = "/addTemplate", method = RequestMethod.POST)
	@ResponseBody
	public String addTemplate(HttpServletRequest httpServletRequest, String templateName, String xmlScript, String params, String note) {
		
		HttpSession session = httpServletRequest.getSession();
        User user = (User)session.getAttribute("user");
		
		XmlJob job = new XmlJob();
		job.setJobType("template");
		job.setXmlJobName(templateName);
		job.setScript(xmlScript);
		job.setNote(note);
		job.setCreateUser(user.getUsername());
		job.setCreateTime(new Date());
		
		Type listType = new TypeToken<LinkedList<TemplateParamDef>>(){}.getType();
        LinkedList<TemplateParamDef> paramsList = new Gson().fromJson(params, listType);
        
        addThreadParams(paramsList);
        
		xmlJobService.insertXmlJob(job, paramsList);
		
		return "success";
	}
	
	private void addThreadParams(List<TemplateParamDef> paramDefs){
		// 默认添加分割任务参数
        // "isSplit", "startDate", "endDate", "taskLoad", "threadNumber"
        TemplateParamDef isSplit = new TemplateParamDef();
        isSplit.setParamName(MultipleThreadJobParams.IS_SPLIT + "");
        isSplit.setParamType(TemplateParamType.MULTITHREAD_TASK_SETTING.getTypeName());
        isSplit.setIsThreadUse("yes");
        paramDefs.add(isSplit);
        
        TemplateParamDef startDate = new TemplateParamDef();
        startDate.setParamName(MultipleThreadJobParams.START_DATE + "");
        startDate.setParamType(TemplateParamType.MULTITHREAD_TASK_SETTING.getTypeName());
        startDate.setIsThreadUse("yes");
        paramDefs.add(startDate);
        
        TemplateParamDef endDate = new TemplateParamDef();
        endDate.setParamName(MultipleThreadJobParams.END_DATE + "");
        endDate.setParamType(TemplateParamType.MULTITHREAD_TASK_SETTING.getTypeName());
        endDate.setIsThreadUse("yes");
        paramDefs.add(endDate);
        
        TemplateParamDef taskLoad = new TemplateParamDef();
        taskLoad.setParamName(MultipleThreadJobParams.TASK_LOAD + "");
        taskLoad.setParamType(TemplateParamType.MULTITHREAD_TASK_SETTING.getTypeName());
        taskLoad.setIsThreadUse("yes");
        paramDefs.add(taskLoad);
        
        TemplateParamDef threadNumber = new TemplateParamDef();
        threadNumber.setParamName(MultipleThreadJobParams.THREAD_NUMBER + "");
        threadNumber.setParamType(TemplateParamType.MULTITHREAD_TASK_SETTING.getTypeName());
        threadNumber.setIsThreadUse("yes");
        paramDefs.add(threadNumber);
	}
	
	@RequestMapping(value = "/updateTemplate", method = RequestMethod.POST)
	@ResponseBody
	public String updateTemplate(HttpServletRequest httpServletRequest, int templateId, String templateName, String xmlScript, String params, String note) {
		
		XmlJob job = new XmlJob();
		job.setXmlJobId(templateId);
		job.setXmlJobName(templateName);
		job.setScript(xmlScript);
		job.setNote(note);
		
		Type listType = new TypeToken<LinkedList<TemplateParamDef>>(){}.getType();
        LinkedList<TemplateParamDef> paramsList = new Gson().fromJson(params, listType);
		
		xmlJobService.updateTemplate(job, paramsList);
		
		return "success";
	}
	
	@RequestMapping(value = "/getTemplateParamDefs", method = RequestMethod.POST)
	@ResponseBody
	public List<TemplateParamDef> getParams(HttpServletRequest httpServletRequest, Integer templateId) {
		return xmlJobService.selectParamDefsByTemplateId(templateId);
	}
	
	@RequestMapping(value = "/addStandardJob", method = RequestMethod.GET)
	public ModelAndView addStandardJob(int tempId) {
		ModelAndView mView = new ModelAndView("EtlXml/addStandardJob");
		setNavigateBar(mView);
		
		mView.addObject("templateId", tempId);
		
		List<Connection> allConnections = connectionService.selectAllConnections(0, 0);
		mView.addObject("allConnections", allConnections);
		
		List<TemplateParamDef> templateParams = xmlJobService.selectParamDefsByTemplateId(tempId);
		mView.addObject("templateParams", templateParams);
		
		return mView;
	}
	
	@RequestMapping(value = "/createJobFromTemp", method = RequestMethod.POST)
	public ModelAndView createJobFromTemp(String jobName, String note, int createFromTemplate, HttpServletRequest request) {
		ModelAndView mView = new ModelAndView("redirect:/EtlXml/list");
		setNavigateBar(mView);
		
		HttpSession session = request.getSession();
        User user = (User)session.getAttribute("user");
		
		XmlJob job = new XmlJob();
		job.setJobType("job");
		job.setXmlJobName(jobName);
		job.setNote(note);
		job.setCreateUser(user.getUsername());
		job.setCreateTime(new Date());
		job.setCreateFromTemplate(createFromTemplate);
		
		List<JobParams> params = new ArrayList<JobParams>();
		
		@SuppressWarnings("unchecked")
		Enumeration<String> paramNames = request.getParameterNames();
		while(paramNames.hasMoreElements()){
			String paramName = paramNames.nextElement();
			if(paramName.startsWith("paramId_")){
				String paramDefId = paramName.replace("paramId_", "");
				TemplateParamDef paramDef = xmlJobService.selectParamDefByParamId(Integer.parseInt(paramDefId));
				
				JobParams jobParam = new JobParams();
				jobParam.setParamDefId(paramDef.getParamId());
				jobParam.setParamValue(request.getParameter(paramName));
				
				params.add(jobParam);
				
			}
		}
		
		for(MultipleThreadJobParams param : MultipleThreadJobParams.values()){
			TemplateParamDef paramDef = xmlJobService.selectParamDefByParamName(createFromTemplate, param.getValue());

			JobParams jobParam = new JobParams();
			jobParam.setParamDefId(paramDef.getParamId());
			jobParam.setParamValue(request.getParameter(param.getValue()));
			
			params.add(jobParam);
		}
		
		xmlJobService.insertJobWithParams(job, params);

		return mView;
	}
	
	@RequestMapping(value = "/createSimpleXmlJob", method = RequestMethod.POST)
	public ModelAndView createSimpleXmlJob(String xmlJobName, String note, String xmlScript, String connections, HttpServletRequest request) {
		ModelAndView mView = new ModelAndView("redirect:/EtlXml/list");
		setNavigateBar(mView);
		
		HttpSession session = request.getSession();
        User user = (User)session.getAttribute("user");
		
		XmlJob job = new XmlJob();
		job.setJobType("simple_job");
		job.setXmlJobName(xmlJobName);
		job.setScript(xmlScript);
		job.setNote(note);
		job.setCreateUser(user.getUsername());
		job.setCreateTime(new Date());
		
		List<JobParams> params = new ArrayList<JobParams>();
		
		if(null != connections){
			for(String connectionId : connections.split(",")){
				JobParams param = new JobParams();
				Connection connection = connectionService.selectConnection(Integer.parseInt(connectionId));
				
				param.setParamName(connection.getConnectionName());
				param.setParamType("connection");
				param.setParamValue("" + connection.getConnectionId());
				
				params.add(param);
			}
		}
		
		xmlJobService.insertJobWithParams(job, params);

		return mView;
	}
	
	@RequestMapping(value = "/del", method = RequestMethod.GET)
	public ModelAndView del(int id) {
		ModelAndView mView = new ModelAndView("redirect:/EtlXml/list");
		setNavigateBar(mView);
		
		xmlJobService.deleteJobOrTemp(id);

		return mView;
	}
	
	@RequestMapping(value = "/editJobOrTemp", method = RequestMethod.GET)
	public ModelAndView editJobOrTempView(String type, int id) {
		ModelAndView mView = new ModelAndView();
		setNavigateBar(mView);

		XmlJob xmlJob = xmlJobService.selectJobById(id);
		mView.addObject("xmlJob", xmlJob);

		// 编码xml脚本，避免特殊字符在前端引起的麻烦
		if(null != xmlJob.getScript()){
			xmlJob.setScript(Encodes.urlEncode(xmlJob.getScript().replace(" ", "%20")));
		}
		
		List<Connection> connections = connectionService.selectAllConnections(0, 0);
		mView.addObject("connections", connections);

		List<JobParams> jobParams = xmlJobService.selectParamsOfJob(id);
		mView.addObject("jobParams", jobParams);
		
		// job参数放到map中，方便前台取值
		Map<String, String> paramValueMap = new HashMap();
		for(JobParams jobparam : jobParams){
			paramValueMap.put("string_" + jobparam.getParamDefId(), jobparam.getParamValue());
		}
		
		mView.addObject("paramValueMap", paramValueMap);
		
		// 找到job参考的模板里参数的原始定义
		Integer referTemplateId = xmlJob.getCreateFromTemplate();
		if(null != referTemplateId){
			XmlJob referTemplate = xmlJobService.selectJobById(referTemplateId);
			if(null != referTemplate){
				List<TemplateParamDef> paramDefs = xmlJobService.selectParamDefsByTemplateId(referTemplate.getXmlJobId());
				mView.addObject("paramDefs", paramDefs);
			}
		}
		
		if ("job".equals(type)) {
			mView.setViewName("EtlXml/editJob");
		} else if ("template".equals(type)) {
			mView.setViewName("EtlXml/editTemplate");
		} else {
			String stringForSelect = "";
			for(JobParams param : jobParams){
				if("connection".equals(param.getParamType())){
					stringForSelect += "'" + param.getParamValue() + "', ";
				}
			}
			
			mView.addObject("stringForSelect", stringForSelect);

			mView.setViewName("EtlXml/editSimpleJob");
		}
		
		return mView;
	}
	
	@RequestMapping(value = "/editSimpleJob", method = RequestMethod.POST)
	public ModelAndView editSimpleJob(int xmlJobId, String xmlJobName, String note, String xmlScript, String connections, HttpServletRequest request) {
		ModelAndView mView = new ModelAndView("redirect:/EtlXml/list");
		setNavigateBar(mView);
		
		XmlJob job = new XmlJob();
		job.setXmlJobId(xmlJobId);
		job.setXmlJobName(xmlJobName);
		job.setScript(xmlScript);
		job.setNote(note);
		
		List<JobParams> params = new ArrayList<JobParams>();
		
		if(null != connections) {
			for(String connectionId : connections.split(",")){
				JobParams param = new JobParams();
				Connection connection = connectionService.selectConnection(Integer.parseInt(connectionId));
				
				param.setParamName(connection.getConnectionName());
				param.setParamType("connection");
				param.setParamValue("" + connection.getConnectionId());
				
				params.add(param);
			}
		}
		
		xmlJobService.updateSimpleJobWithParams(job, params);
		
		return mView;
	}
	
	@RequestMapping(value = "/editStandardJob", method = RequestMethod.POST)
	public ModelAndView editStandardJob(int xmlJobId, String jobName, String note, HttpServletRequest request) {
		ModelAndView mView = new ModelAndView("redirect:/EtlXml/list");
		setNavigateBar(mView);
		
		XmlJob job = xmlJobService.selectJobById(xmlJobId);
		job.setXmlJobName(jobName);
		job.setNote(note);
		
		List<JobParams> params = new ArrayList<JobParams>();
		
		@SuppressWarnings("unchecked")
		Enumeration<String> paramNames = request.getParameterNames();
		while(paramNames.hasMoreElements()){
			String paramName = paramNames.nextElement();
			if(paramName.startsWith("paramId_")){
				String paramDefId = paramName.replace("paramId_", "");
				JobParams jobParam = xmlJobService.selectJobParamByParamDefId(Integer.parseInt(paramDefId));
				
				jobParam.setParamValue(request.getParameter(paramName));
				
				params.add(jobParam);
			}
		}
		
		for(MultipleThreadJobParams threadParam : MultipleThreadJobParams.values()){
			TemplateParamDef paramDef = xmlJobService.selectParamDefByParamName(job.getCreateFromTemplate(), threadParam.getValue());
			JobParams jobParam = xmlJobService.selectJobParamByParamDefId(paramDef.getParamId());
			jobParam.setParamValue(request.getParameter(threadParam.getValue()));
			params.add(jobParam);
		}
		
		xmlJobService.updateStandardJobWithParams(job, params);
		
		return mView;
	}
	
	@RequestMapping(value = "/executeOnce", method = RequestMethod.POST)
	@ResponseBody
	public String executeOnce(int xmlJobId, HttpServletRequest request) {
		
		HttpSession session = request.getSession();
        User user = (User)session.getAttribute("user");
		
		try {
			XmlJob xmlJob = xmlJobService.selectJobById(xmlJobId);
			JobExecuteHelper.executeJobImmediate(xmlJob.getXmlJobId(), xmlJob.getXmlJobName(), user.getUsername());
			return "success";
		} catch (Exception e) {
			e.printStackTrace();
			return e.getMessage();
		}
	}
	
	@RequestMapping(value = "/showFinalScript", method = RequestMethod.POST)
	@ResponseBody
	public String showFinalScript(int xmlJobId) {
		return generateXmlService.GetJobEtlXml(xmlJobId);
	}
}
